package org.huamoxi.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
import org.huamoxi.constant.RedisConstants;
import org.huamoxi.constant.SecurityConstants;
import org.huamoxi.utils.CacheUtils;
import org.huamoxi.utils.JwtUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebFilter
@Component
public class TokenCheckFilter extends OncePerRequestFilter {

    @Resource
    CacheUtils cacheUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String header = request.getHeader("token");
        if (header == null || !header.startsWith("Bearer ")) {
            //如果携带错误的token，则给用户提示请登录！
            // chain.doFilter(request, response);
            backErrMsg(response, "请先登录");
        } else {
            //如果携带了正确格式的token要先得到token
            String token = header.replace("Bearer ", "");
            // 校验
            try {
                Claims claims = JwtUtils.verifyToken(token);

                if (claims.get("username") != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    // 从redis获取用户信息
                    String redisToken = cacheUtils.get(RedisConstants.TOKEN_CACHE_KEY_PREFIX + claims.get("id"));
                    String redisLoginUser = cacheUtils.get(RedisConstants.LOGIN_USER_CACHE_KEY + claims.get("id"));
//                    Set<Object> ro = cacheUtils.sGet(RedisConstants.USER_CACHE_AUTHORITIES + claims.get("id"));
//                    List<GrantedAuthority> redisAuthorities = Arrays.asList();
                    if (StrUtil.isEmpty(redisToken) || StrUtil.isEmpty(redisLoginUser)) {
                        backErrMsg(response, "请先登录");
                    }

                    // 获取角色
                    String jsonStr = cacheUtils.get(RedisConstants.USER_CACHE_AUTHORITIES + claims.get("id"));

                    List<GrantedAuthority> authorities = JSON.parseArray(jsonStr, GrantedAuthority.class);
                    System.out.println(authorities);

                    UsernamePasswordAuthenticationToken authResult = new UsernamePasswordAuthenticationToken(claims.get(SecurityConstants.NAME), null, authorities);
                    SecurityContextHolder.getContext().setAuthentication(authResult);
                }

                chain.doFilter(request, response);
            } catch (Exception e) {
                e.printStackTrace();
                backErrMsg(response, "请先登录");
            }
        }
    }

    private void backErrMsg(HttpServletResponse response, String msg) {
        //如果携带错误的token，则给用户提示请登录！
        // chain.doFilter(request, response);
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Map resultMap = new HashMap();
        resultMap.put("code", HttpServletResponse.SC_FORBIDDEN);
        resultMap.put("msg", msg);
        out.write(JSONUtil.toJsonStr(resultMap));
        out.flush();
        if (out != null) {
            out.close();
        }
    }
}
